home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1990,1991,1992 Chris and John Downey */
- #ifndef lint
- static char *sccsid = "@(#)startup.c 2.3 (Chris & John Downey) 9/4/92";
- #endif
-
- /***
-
- * program name:
- xvi
- * function:
- PD version of UNIX "vi" editor, with extensions.
- * module name:
- main.c
- * module function:
- Entry point for xvi; setup, argument parsing and signal handling.
- * history:
- STEVIE - ST Editor for VI Enthusiasts, Version 3.10
- Originally by Tim Thompson (twitch!tjt)
- Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
- Heavily modified by Chris & John Downey
-
- ***/
-
- #include "xvi.h"
-
- /*
- * References to the current cursor position, and the window
- * and buffer into which it references. These make the code a
- * lot simpler, but we have to be a bit careful to update them
- * whenever necessary.
- */
- Buffer *curbuf;
- Xviwin *curwin;
-
- /*
- * Global variables.
- */
- state_t State = NORMAL; /* This is the current state of the command */
- /* interpreter. */
-
- unsigned echo; /*
- * bitmap controlling the verbosity of
- * screen output (see xvi.h for details).
- */
-
- int indentchars; /* number of chars indented on current line */
-
- volatile unsigned char
- kbdintr; /*
- * global flag set when a keyboard interrupt
- * is received
- */
-
- bool_t imessage; /*
- * global flag to indicate whether we should
- * display the "Interrupted" message
- */
-
- /*
- * Internal routines.
- */
- static void usage P((void));
-
- Xviwin *
- xvi_startup(vs, argc, argv, envp)
- VirtScr *vs;
- int argc;
- char *argv[];
- char *envp; /* init string from the environment */
- {
- char *tag = NULL; /* tag from command line */
- char *pat = NULL; /* pattern from command line */
- long line = -1; /* line number from command line */
- char **files;
- int numfiles = 0;
- int count;
- char *env;
- ignore_signals();
-
- /*
- * Initialise parameter module.
- */
- init_params();
-
- /*
- * Initialise yank/put module.
- */
- init_yankput();
-
- /*
- * The critical path this code has to follow is quite tricky.
- * We can't really run the "env" string until after we've set
- * up the first screen window because we don't know what the
- * commands in "env" might do: they might, for all we know,
- * want to display something. And we can't set up the first
- * screen window until we've set up the terminal interface.
- *
- * Also, we can't read the command line arguments until after
- * we've run the "env" string because a "-s param=value" argument
- * should override any setting of that parameter in the environment.
- *
- * All this means that the usage() function, which tells the
- * user that the command line syntax was wrong, can only be
- * called after the display interface has already been set up,
- * which means we must be in visual mode. So usage() has to
- * switch back to system mode (otherwise, on systems where
- * sys_startv() & sys_endv() switch display pages,
- * the user will never see the output of usage()). So ...
- */
-
- /*
- * Set up the first buffer and screen window.
- * Must call sys_init first.
- */
- curbuf = new_buffer();
- if (curbuf == NULL) {
- sys_endv();
- (void) fputs("Can't allocate buffer memory.\n", stderr);
- sys_exit(2);
- }
- curwin = init_window(vs);
- if (curwin == NULL) {
- sys_endv();
- (void) fputs("Can't allocate buffer memory.\n", stderr);
- sys_exit(2);
- }
-
- /*
- * Connect the two together.
- */
- map_window_onto_buffer(curwin, curbuf);
-
- init_sline(curwin);
-
- /*
- * Save a copy of the passed environment string in case it was
- * obtained from getenv(), so that the subsequent call we make
- * to get the SHELL parameter value does not overwrite it.
- */
- if (envp != NULL) {
- env = strsave(envp);
- }
- else {
- env = NULL;
- }
-
- /*
- * Try to obtain a value for the "shell" parameter from the
- * environment variable SHELL. If this is NULL, do not override
- * any existing value. The system interface code (sys_init()) is
- * free to set up a default value, and the initialisation string
- * in the next part of the startup is free to override both that
- * value and the one from the environment.
- */
- {
- char *sh;
-
- sh = getenv("SHELL");
- if (sh != NULL) set_param(P_shell, sh);
- }
-
- /*
- * Run any initialisation string passed to us.
- *
- * We can't really do this until we have set up the terminal
- * because we don't know what the initialisation string might do.
- */
- if (env != NULL) {
- register char *ep;
- register bool_t escaped = FALSE;
-
- /*
- * Commands in the initialization string can be
- * separated by '|' (or '\n'), but a literal '|' or
- * '\n' can be escaped by a preceding '\\', so we have
- * to process the string, looking for all three
- * characters.
- */
- for (ep = env; *ep;) {
- switch (*ep++) {
- case '\\':
- escaped = TRUE;
- continue;
- case '|':
- case '\n':
- if (escaped) {
- register char *s, *d;
-
- for (d = (s = --ep) - 1; (*d++ = *s++) != '\0'; )
- ;
- }
- else {
- ep[-1] = '\0';
- do_colon(env, FALSE);
- env = ep;
- }
- /* fall through ... */
- default:
- escaped = FALSE;
- }
- }/*for ep */
- if (ep > env) {
- do_colon(env, FALSE);
- }
- }/*if env*/
-
- /*
- * Process the command line arguments.
- *
- * We can't really do this until we have run the "env" string,
- * because "-s param=value" on the command line should override
- * parameter setting in the environment.
- *
- * This is a bit awkward because it means usage() is called
- * when we're already in vi mode (which means, among other
- * things, that display pages may have been swapped).
- */
- for (count = 1;
- count < argc && (argv[count][0] == '-' || argv[count][0] == '+');
- count++) {
-
- if (argv[count][0] == '-') {
- switch (argv[count][1]) {
- case 't':
- /*
- * -t tag or -ttag
- */
- if (numfiles != 0) usage();
- if (argv[count][2] != '\0') {
- tag = &(argv[count][2]);
- }
- else
- if (count < (argc - 1)) {
- count += 1;
- tag = argv[count];
- }
- else {
- usage();
- }
- break;
-
- case 's':
- /*
- * -s param=value or
- * -sparam=value
- */
- if (argv[count][2] != '\0') {
- argv[count] += 2;
- }
- else
- if (count < (argc - 1)) {
- count += 1;
- }
- else {
- usage();
- }
- do_set(curwin, 1, &argv[count], FALSE);
- break;
-
- default:
- usage();
- }
-
- }
- else /* argv[count][0] == '+' */ {
- char nc;
-
- /*
- * "+n file" or "+/pat file"
- */
- if (count >= (argc - 1)) usage();
-
- nc = argv[count][1];
- if (nc == '/') {
- pat = &(argv[count][2]);
- }
- else
- if (is_digit(nc)) {
- line = atol(&(argv[count][1]));
- } else
- if (nc == '\0') {
- line = 0;
- }
- else {
- usage();
- }
- count += 1;
- files = &argv[count];
- numfiles = 1;
- }/* else */
- }
- if (numfiles != 0 || tag != NULL) {
- /*
- * If we found "-t tag", "+n file" or "+/pat file" on
- * the command line, we don't want to see any more
- * file names.
- */
- if (count < argc) usage();
- }
- else {
- /*
- * Otherwise, file names are valid.
- */
- numfiles = argc - count;
- if (numfiles > 0) {
- files = &(argv[count]);
- }
- }
-
- /*
- * Initialise the cursor and top of screen pointers
- * to the start of the first buffer. Note that the
- * bottom of screen pointer is also set up, as some
- * code (e.g. move_window_to_cursor) depends on it.
- */
- curwin->w_topline = curbuf->b_file;
- curwin->w_botline = curbuf->b_file->l_next;
- move_cursor(curwin, curbuf->b_file, 0);
- curwin->w_col = 0;
- curwin->w_row = 0;
-
- /*
- * Clear the window.
- *
- * It doesn't make sense to do this until we have a value for
- * Pn(P_colour).
- */
- clear(curwin);
-
- if (numfiles != 0) {
- if (line < 0 && pat == NULL)
- echo = e_CHARUPDATE | e_SHOWINFO;
-
- do_next(curwin, numfiles, files, FALSE);
-
- if (pat != NULL) {
- echo = e_CHARUPDATE | e_SHOWINFO | e_REGERR | e_NOMATCH;
- (void) dosearch(curwin, pat, '/');
- }
- else if (line >= 0) {
- echo = e_CHARUPDATE | e_SHOWINFO;
- do_goto((line > 0) ? line : MAX_LINENO);
- }
-
- }
- else if (tag != NULL) {
- echo = e_CHARUPDATE | e_SHOWINFO | e_REGERR | e_NOMATCH;
- if (do_tag(curwin, tag, FALSE, TRUE, FALSE) == FALSE) {
- /*
- * Failed to find tag - wait for a while
- * to allow user to read tags error and then
- * display the "no file" message.
- */
- sleep(2);
- show_file_info(curwin);
- }
- }
- else {
- echo = e_CHARUPDATE | e_SHOWINFO;
- show_file_info(curwin);
- }
-
- setpcmark(curwin);
-
- echo = e_CHARUPDATE;
-
- /*
- * Ensure we are at the right screen position.
- */
- move_window_to_cursor(curwin);
-
- /*
- * Draw the screen.
- */
- update_all();
-
- /*
- * Update the cursor position on the screen, and go there.
- */
- cursupdate(curwin);
- wind_goto(curwin);
-
- /*
- * Allow everything.
- */
- echo = e_ANY;
-
- catch_signals();
-
- if (env != NULL) {
- free(env);
- }
-
- return(curwin);
- }
-
- /*
- * Print usage message and die.
- *
- * This function is only called after we have set the terminal to vi
- * mode.
- *
- * The system interface functions have to ensure that it's safe to
- * call sys_exit() when sys_endv() has already been called (& there
- * hasn't necessarily been any intervening sys_startv()).
- */
- static void
- usage()
- {
- sys_endv();
- (void) fputs("Usage: xvi { options } [ file ... ]\n", stderr);
- (void) fputs(" xvi { options } -t tag\n", stderr);
- (void) fputs(" xvi { options } +[num] file\n", stderr);
- (void) fputs(" xvi { options } +/pat file\n", stderr);
- (void) fputs("\nOptions are:\n", stderr);
- (void) fputs(" -s [no]boolean-parameter\n", stderr);
- (void) fputs(" -s parameter=value\n", stderr);
- sys_exit(1);
- }
-